package http

import (
	"fmt"
	"net/http"
	"regexp"
	"strings"
	"xrt/components/http/session/sess"
	"xrt/utils"
	"xrt/utils/file/log"
)

func (h *xHttpLayer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	startTime := utils.GetTimestampMS()
	url := r.URL.Path
	method := strings.Title(strings.ToLower(r.Method))
	//处理Session
	var sessionStore session.Store
	if h.sessionManager != nil {
		if store, err := h.sessionManager.SessionStart(w, r); err != nil {
			log.Errorf("Session Loading Failed, Reason: [%s].", err.Error())
		} else {
			sessionStore = store
		}
	}
	//将尾部的斜杠'/'过滤
	if len(url) > 1 && url[len(url)-1] == '/' {
		url = url[0 : len(url)-1]
	}

	found := false
	var methodC func(*XHttp)
	var pattern []string
	//判断是否存在访问路由
	for path := range h.patternMap {
		reCompile, _ := regexp.Compile("^" + path + "$")
		if reCompile.Match([]byte(url)) {
			//正则匹配Url, 生成Pattern列表
			for _, p := range utils.Map(reCompile.FindSubmatch([]byte(url)), func(pat interface{}) interface{} {
				return string(pat.([]byte))
			}) {
				pattern = append(pattern, p.(string))
			}

			//判定是否存在方法
			if _, found = h.patternMap[path][method]; found {
				methodC = h.patternMap[path][method]
			} else {
				if _, found = h.patternMap[path]["Default"]; found {
					methodC = h.patternMap[path]["Default"]
				}
			}
		}
	}

	//跨域处理
	if h.cross {
		w.Header().Set("Access-Control-Allow-Origin", "*")             //允许访问所有域
		w.Header().Add("Access-Control-Allow-Headers", "Content-Type") //header的类型
		//w.Header().Set("content-type", "application/json")             //返回数据格式是json
	}

	nbHttp := XHttp{Writer: w, Reader: r, Path: url, Pattern: pattern, Method: method, Session: sessionStore, sync: h, async: h.async}
	if found {
		methodC(&nbHttp)
	} else {
		//找不到则返回404
		nbHttp.toNotFound()
	}

	//保存Session
	if nbHttp.Session != nil {
		sessionStore.SessionRelease(w)
	}

	logOut := fmt.Sprintf("Request Url: [%s], Method: [%s]. Cost Time: [%.2fms].", url, method, utils.GetTimestampMS()-startTime)
	if nbHttp.GetRespStatus() == http.StatusNotFound {
		logOut += " Not Found."
	}
	log.Debug(logOut)
}
